//! # RustCloud 统一错误处理模块
//!
//! 本模块定义了 RustCloud 框架中所有组件使用的统一错误类型。

use std::fmt;
use std::error::Error as StdError;
use std::collections::HashMap;
use thiserror::Error;

// =============================================================================
// 核心错误类型
// =============================================================================

/// RustCloud 统一错误类型
#[derive(Debug, Clone)]
pub struct RustCloudError {
    /// 错误类型
    pub kind: ErrorKind,
    /// 错误消息
    pub message: String,
    /// 错误上下文
    pub context: HashMap<String, String>,
    /// 错误代码（可选）
    pub code: Option<String>,
    /// 时间戳
    pub timestamp: chrono::DateTime<chrono::Utc>,
    /// 源错误
    pub source: Option<String>,
    /// 错误ID
    pub error_id: String,
}

impl RustCloudError {
    /// 创建新的错误
    pub fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
        Self {
            kind,
            message: message.into(),
            context: HashMap::new(),
            code: None,
            timestamp: chrono::Utc::now(),
            source: None,
            error_id: uuid::Uuid::new_v4().to_string(),
        }
    }

    /// 添加错误上下文
    pub fn with_context(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
        self.context.insert(key.into(), value.into());
        self
    }

    /// 设置源错误
    pub fn with_source<E: StdError>(mut self, source: E) -> Self {
        self.source = Some(source.to_string());
        self
    }

    /// 创建网络错误
    pub fn network_error(message: impl Into<String>) -> Self {
        Self::new(ErrorKind::Network(NetworkError::ConnectionFailed), message)
    }

    /// 创建注册中心错误
    pub fn registry_error(message: impl Into<String>) -> Self {
        Self::new(ErrorKind::Registry(RegistryError::RegistrationFailed), message)
    }

    /// 创建负载均衡错误
    pub fn load_balancer_error(message: impl Into<String>) -> Self {
        Self::new(ErrorKind::LoadBalancer(LoadBalancerError::NoAvailableInstances), message)
    }

    /// 创建熔断器错误
    pub fn circuit_breaker_error(message: impl Into<String>) -> Self {
        Self::new(ErrorKind::CircuitBreaker(CircuitBreakerError::CircuitOpen), message)
    }

    /// 创建配置错误
    pub fn config_error(message: impl Into<String>) -> Self {
        Self::new(ErrorKind::Config(ConfigError::InvalidConfiguration), message)
    }

    /// 创建依赖注入错误
    pub fn di_error(message: impl Into<String>) -> Self {
        Self::new(ErrorKind::Core(CoreError::DependencyInjection), message)
    }

    /// 是否为临时错误（可重试）
    pub fn is_transient(&self) -> bool {
        matches!(self.kind, 
            ErrorKind::Network(NetworkError::Timeout) |
            ErrorKind::Network(NetworkError::ConnectionFailed) |
            ErrorKind::Registry(RegistryError::TemporaryFailure) |
            ErrorKind::LoadBalancer(LoadBalancerError::NoAvailableInstances)
        )
    }

    /// 获取HTTP状态码映射
    pub fn to_http_status(&self) -> u16 {
        match &self.kind {
            ErrorKind::Core(CoreError::Timeout) => 408,
            ErrorKind::Network(_) => 503,
            ErrorKind::Registry(_) => 503,
            ErrorKind::LoadBalancer(_) => 503,
            ErrorKind::CircuitBreaker(_) => 503,
            ErrorKind::Config(_) => 500,
            ErrorKind::Security(SecurityError::AuthenticationFailed) => 401,
            ErrorKind::Security(SecurityError::AuthorizationFailed) => 403,
            ErrorKind::Business(BusinessError::ValidationFailed) => 400,
            ErrorKind::Business(BusinessError::NotFound) => 404,
            _ => 500,
        }
    }
}

impl fmt::Display for RustCloudError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[{}] {}: {}", self.error_id, self.kind, self.message)?;
        if !self.context.is_empty() {
            write!(f, " (context: {:?})", self.context)?;
        }
        if let Some(ref source) = self.source {
            write!(f, " caused by: {}", source)?;
        }
        Ok(())
    }
}

impl StdError for RustCloudError {}

// =============================================================================
// 错误类型分类
// =============================================================================

/// 错误类型枚举
#[derive(Debug, Clone, PartialEq)]
pub enum ErrorKind {
    Core(CoreError),
    Network(NetworkError),
    Registry(RegistryError),
    LoadBalancer(LoadBalancerError),
    CircuitBreaker(CircuitBreakerError),
    Config(ConfigError),
    Security(SecurityError),
    Business(BusinessError),
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ErrorKind::Core(e) => write!(f, "Core({})", e),
            ErrorKind::Network(e) => write!(f, "Network({})", e),
            ErrorKind::Registry(e) => write!(f, "Registry({})", e),
            ErrorKind::LoadBalancer(e) => write!(f, "LoadBalancer({})", e),
            ErrorKind::CircuitBreaker(e) => write!(f, "CircuitBreaker({})", e),
            ErrorKind::Config(e) => write!(f, "Config({})", e),
            ErrorKind::Security(e) => write!(f, "Security({})", e),
            ErrorKind::Business(e) => write!(f, "Business({})", e),
        }
    }
}

// =============================================================================
// 具体错误类型
// =============================================================================

#[derive(Debug, Clone, PartialEq)]
pub enum CoreError {
    InternalError,
    Timeout,
    DependencyInjection,
    SerializationError,
}

impl fmt::Display for CoreError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CoreError::InternalError => write!(f, "InternalError"),
            CoreError::Timeout => write!(f, "Timeout"),
            CoreError::DependencyInjection => write!(f, "DependencyInjection"),
            CoreError::SerializationError => write!(f, "SerializationError"),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum NetworkError {
    ConnectionFailed,
    Timeout,
    HttpError,
    DnsResolutionFailed,
}

impl fmt::Display for NetworkError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            NetworkError::ConnectionFailed => write!(f, "ConnectionFailed"),
            NetworkError::Timeout => write!(f, "Timeout"),
            NetworkError::HttpError => write!(f, "HttpError"),
            NetworkError::DnsResolutionFailed => write!(f, "DnsResolutionFailed"),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum RegistryError {
    RegistrationFailed,
    DiscoveryFailed,
    HealthCheckFailed,
    TemporaryFailure,
}

impl fmt::Display for RegistryError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            RegistryError::RegistrationFailed => write!(f, "RegistrationFailed"),
            RegistryError::DiscoveryFailed => write!(f, "DiscoveryFailed"),
            RegistryError::HealthCheckFailed => write!(f, "HealthCheckFailed"),
            RegistryError::TemporaryFailure => write!(f, "TemporaryFailure"),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum LoadBalancerError {
    NoAvailableInstances,
    InstanceSelectionFailed,
    StrategyConfigurationError,
}

impl fmt::Display for LoadBalancerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            LoadBalancerError::NoAvailableInstances => write!(f, "NoAvailableInstances"),
            LoadBalancerError::InstanceSelectionFailed => write!(f, "InstanceSelectionFailed"),
            LoadBalancerError::StrategyConfigurationError => write!(f, "StrategyConfigurationError"),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum CircuitBreakerError {
    CircuitOpen,
    ConfigurationError,
    StateTransitionError,
}

impl fmt::Display for CircuitBreakerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CircuitBreakerError::CircuitOpen => write!(f, "CircuitOpen"),
            CircuitBreakerError::ConfigurationError => write!(f, "ConfigurationError"),
            CircuitBreakerError::StateTransitionError => write!(f, "StateTransitionError"),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum ConfigError {
    InvalidConfiguration,
    ConfigFileNotFound,
    ParseError,
    ValidationFailed,
}

impl fmt::Display for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ConfigError::InvalidConfiguration => write!(f, "InvalidConfiguration"),
            ConfigError::ConfigFileNotFound => write!(f, "ConfigFileNotFound"),
            ConfigError::ParseError => write!(f, "ParseError"),
            ConfigError::ValidationFailed => write!(f, "ValidationFailed"),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum SecurityError {
    AuthenticationFailed,
    AuthorizationFailed,
    InvalidToken,
    TokenExpired,
}

impl fmt::Display for SecurityError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            SecurityError::AuthenticationFailed => write!(f, "AuthenticationFailed"),
            SecurityError::AuthorizationFailed => write!(f, "AuthorizationFailed"),
            SecurityError::InvalidToken => write!(f, "InvalidToken"),
            SecurityError::TokenExpired => write!(f, "TokenExpired"),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum BusinessError {
    ValidationFailed,
    NotFound,
    Conflict,
    BusinessRuleViolation,
}

impl fmt::Display for BusinessError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            BusinessError::ValidationFailed => write!(f, "ValidationFailed"),
            BusinessError::NotFound => write!(f, "NotFound"),
            BusinessError::Conflict => write!(f, "Conflict"),
            BusinessError::BusinessRuleViolation => write!(f, "BusinessRuleViolation"),
        }
    }
}

// =============================================================================
// 结果类型和转换
// =============================================================================

/// RustCloud 统一结果类型
pub type RustCloudResult<T> = Result<T, RustCloudError>;

/// 从标准IO错误转换
impl From<std::io::Error> for RustCloudError {
    fn from(error: std::io::Error) -> Self {
        RustCloudError::network_error("IO错误").with_source(error)
    }
}

/// 从JSON序列化错误转换
impl From<serde_json::Error> for RustCloudError {
    fn from(error: serde_json::Error) -> Self {
        RustCloudError::new(ErrorKind::Core(CoreError::SerializationError), "JSON序列化错误")
            .with_source(error)
    }
}

/// 从HTTP客户端错误转换
impl From<reqwest::Error> for RustCloudError {
    fn from(error: reqwest::Error) -> Self {
        let error_kind = if error.is_timeout() {
            ErrorKind::Network(NetworkError::Timeout)
        } else if error.is_connect() {
            ErrorKind::Network(NetworkError::ConnectionFailed)
        } else {
            ErrorKind::Network(NetworkError::HttpError)
        };
        RustCloudError::new(error_kind, "HTTP请求错误").with_source(error)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_error_creation() {
        let error = RustCloudError::network_error("测试网络错误")
            .with_context("service", "user-service");
        
        assert!(matches!(error.kind, ErrorKind::Network(_)));
        assert_eq!(error.message, "测试网络错误");
        assert_eq!(error.context.get("service"), Some(&"user-service".to_string()));
    }

    #[test]
    fn test_error_transient() {
        let network_error = RustCloudError::network_error("网络超时");
        assert!(network_error.is_transient());

        let config_error = RustCloudError::config_error("配置错误");
        assert!(!config_error.is_transient());
    }

    #[test]
    fn test_http_status_mapping() {
        let network_error = RustCloudError::network_error("网络错误");
        assert_eq!(network_error.to_http_status(), 503);

        let auth_error = RustCloudError::new(
            ErrorKind::Security(SecurityError::AuthenticationFailed),
            "认证失败"
        );
        assert_eq!(auth_error.to_http_status(), 401);
    }
}